Bagaimana cara terbaik saya mengelola membuat rilis kode sumber terbuka dari kode penelitian rahasia perusahaan saya?

13

Perusahaan saya (sebut saja Acme Technology) memiliki perpustakaan sekitar seribu file sumber yang awalnya berasal dari grup riset Acme Labs, diinkubasi dalam grup pengembangan selama beberapa tahun, dan baru-baru ini diberikan kepada beberapa pelanggan di bawah tanpa pengungkapan. Acme bersiap-siap untuk melepaskan mungkin 75% dari kode ke komunitas open source. 25% lainnya akan dirilis nanti, tetapi untuk saat ini, tidak siap untuk digunakan pelanggan atau berisi kode yang terkait dengan inovasi masa depan yang mereka butuhkan untuk tetap berada di luar tangan para pesaing.

Kode saat ini diformat dengan #ifdefs yang memungkinkan basis kode yang sama untuk bekerja dengan platform pra-produksi yang akan tersedia untuk para peneliti universitas dan berbagai pelanggan komersial yang jauh lebih luas begitu masuk ke open source, sementara pada saat yang sama menjadi tersedia untuk eksperimen dan pembuatan prototipe serta pengujian kompatibilitas maju dengan platform masa depan. Mempertahankan basis kode tunggal dianggap penting untuk ekonomi (dan kewarasan) grup saya yang akan mengalami kesulitan mempertahankan dua salinan secara paralel.

File di basis kami saat ini terlihat seperti ini:

> // Copyright 2012 (C) Acme Technology, All Rights Reserved.
> // Very large, often varied and restrictive copyright license in English and French,
> // sometimes also embedded in make files and shell scripts with varied 
> // comment styles. 
> 
> 
>   ... Usual header stuff...
>
> void initTechnologyLibrary() {
>     nuiInterface(on);
> #ifdef  UNDER_RESEARCH
>     holographicVisualization(on);
> #endif
> }

Dan kami ingin mengubahnya menjadi seperti:

> // GPL Copyright (C) Acme Technology Labs 2012, Some rights reserved.
> // Acme appreciates your interest in its technology, please contact [email protected] 
> // for technical support, and www.acme.com/emergingTech for updates and RSS feed.
> 
>   ... Usual header stuff...
>
> void initTechnologyLibrary() {
>     nuiInterface(on);
> }

Apakah ada alat, parse library, atau skrip populer yang dapat menggantikan hak cipta dan menghapus tidak hanya #ifdefs, tetapi variasi seperti #jika ditentukan (UNDER_RESEARCH), dll.?

Kode saat ini di Git dan kemungkinan akan di-host di suatu tempat yang menggunakan Git. Akankah ada cara untuk menautkan repositori dengan aman bersama sehingga kita dapat mengintegrasikan kembali perbaikan kami dengan versi open source secara efisien? Saran tentang perangkap lain dipersilahkan.

Pengembang Don
sumber
13
Basis kode ini berteriak untuk cabang.
Florian Margaine
Contoh menggunakan cabang untuk tujuan ini akan sangat disambut.
PengembangDon

Jawaban:

6

Tampaknya seperti itu tidak akan terlalu sulit untuk menulis script untuk mengurai preprosesor, membandingkannya dengan daftar konstanta didefinisikan ( UNDER_RESEARCH, FUTURE_DEVELOPMENT, dll) dan, jika direktif dapat dievaluasi untuk keterberian palsu apa yang didefinisikan, menghapus semuanya ke yang berikutnya #endif.

Dengan Python, saya akan melakukan sesuatu seperti,

import os

src_dir = 'src/'
switches = {'UNDER_RESEARCH': True, 'OPEN_SOURCE': False}
new_header = """// GPL Copyright (C) Acme Technology Labs 2012, Some rights reserved.
// Acme appreciates your interest in its technology, please contact [email protected] 
// for technical support, and www.acme.com/emergingTech for updates and RSS feed.
"""

filenames = os.listdir(src_dir)
for fn in filenames:
    contents = open(src_dir+fn, 'r').read().split('\n')
    outfile = open(src_dir+fn+'-open-source', 'w')
    in_header = True
    skipping = False
    for line in contents:
        # remove original header
        if in_header and (line.strip() == "" or line.strip().startswith('//')):
            continue
        elif in_header:
            in_header = False
            outfile.write(new_header)

        # skip between ifdef directives
        if skipping:
            if line.strip() == "#endif":
                skipping = False
            continue
        # check
        if line.strip().startswith("#ifdef"):
            # parse #ifdef (maybe should be more elegant)
            # this assumes a form of "#ifdef SWITCH" and nothing else
            if line.strip().split()[1] in switches.keys():
                skipping = True
                continue

        # checking for other forms of directives is left as an exercise

        # got this far, nothing special - echo the line
        outfile.write(line)
        outfile.write('\n')

Saya yakin ada cara yang lebih elegan untuk melakukannya, tetapi ini cepat dan kotor dan sepertinya menyelesaikan pekerjaan.

WasabiFlux
sumber
Wow terima kasih. Ada banyak logika yang berpotensi untuk membuat filter yang baik dan saya menghargai contoh Anda. Saya berharap dapat menemukan sesuatu untuk digunakan kembali, dan mesin pengembangan saya cepat dengan memori besar sehingga kinerjanya bukan masalah yang sangat besar untuk menjalankan filter terpisah untuk hak cipta dan definisi, atau untuk menjalankan filter define lebih dari sekali. Kami sebenarnya memiliki beberapa definisi yang terkait dengan kata kunci yang menunjuk beberapa proyek masa depan dan beberapa proyek masa lalu yang tidak akan dirilis open source, tetapi masih digunakan secara internal dan oleh pelanggan adopsi awal.
PengembangDon
3

Saya berpikir tentang meneruskan kode Anda melalui preprocessor untuk hanya memperluas makro, sehingga hanya menghasilkan bagian yang menarik di #ifdefs.

Sesuatu seperti ini seharusnya bekerja:

gcc -E yourfile.c

Tapi:

  • Anda akan kehilangan semua komentar. Anda dapat menggunakannya -CCuntuk (melestarikannya), tetapi Anda tetap harus menghapus pemberitahuan hak cipta yang lama
  • #includes juga diperluas, sehingga Anda akan berakhir dengan file besar yang berisi semua konten dari file header yang disertakan
  • Anda akan kehilangan makro "standar".

Mungkin ada cara untuk membatasi makro mana yang diperluas; Namun saran saya di sini adalah untuk membagi hal-hal, daripada melakukan pemrosesan (berpotensi berbahaya) pada file (omong-omong, bagaimana Anda berencana untuk mempertahankannya setelah itu? misalnya memperkenalkan kembali kode dari versi opensource ke sumber tertutup Anda?).

Yaitu, coba letakkan kode yang Anda inginkan untuk membuka sumber di pustaka eksternal sebanyak mungkin, lalu gunakan kode itu seperti yang Anda lakukan dengan pustaka lain, diintegrasikan dengan pustaka sumber tertutup "khusus" lainnya.

Mungkin butuh sedikit lebih lama pada awalnya untuk mengetahui cara merestrukturisasi sesuatu, tapi itu jelas cara yang tepat untuk mencapai ini.

redShadow
sumber
Saya telah mempertimbangkan apakah mungkin ada sesuatu yang bisa dilakukan dengan preprocessor untuk secara selektif menghilangkan blok yang belum kami lepaskan. Kode ini kompleks dan kami kemungkinan akan membutuhkan lebih banyak komentar daripada kurang, tetapi saran Anda tentu layak dimiliki dalam daftar curah pendapat. Pertanyaan WRT tentang bagaimana kami berencana untuk mempertahankan sumber dan memindahkan kode ke belakang dan ke depan ke komunitas, ada perencanaan lebih lanjut diperlukan. Membawa kode ke kode hak milik menimbulkan beberapa pertanyaan bagus.
PengembangDon
2

Saya punya solusi tetapi akan membutuhkan sedikit usaha

pypreprocessor adalah perpustakaan yang menyediakan preprocessor c-style murni untuk python yang juga dapat digunakan sebagai GPP (General Purpose Pre-Processor) untuk jenis kode sumber lainnya.

Inilah contoh dasar:

from pypreprocessor import pypreprocessor

pypreprocessor.input = 'input_file.c'
pypreprocessor.output = 'output_file.c'
pypreprocessor.removeMeta = True
pypreprocessor.parse()

Preprosesor sangat sederhana. Itu membuat melewati sumber dan kondisional mengomentari sumber berdasarkan apa yang didefinisikan.

Tentukan dapat diatur baik melalui pernyataan #define di sumber atau dengan mengaturnya di daftar pypreprocessor.defines.

Mengatur parameter input / output memungkinkan Anda untuk secara eksplisit menentukan file mana yang dibuka / ditutup sehingga satu preprocessor dapat diatur untuk batch memproses sejumlah besar file jika diinginkan.

Mengatur parameter removeMeta ke True, preprocessor harus secara otomatis mengekstrak setiap dan semua pernyataan preprocessor hanya menyisakan kode pasca-pemrosesan.

Catatan: Biasanya ini tidak perlu diatur secara eksplisit karena python menghapus kode komentar secara otomatis selama kompilasi menjadi bytecode.

Saya hanya melihat satu case edge. Karena Anda mencari sumber preprocess C, Anda mungkin ingin mengatur prosesor mendefinisikan secara eksplisit (yaitu melalui pypreprocessor.defines) dan memintanya untuk mengabaikan pernyataan #define dalam sumber. Itu seharusnya mencegahnya secara tidak sengaja menghapus konstanta yang dapat Anda gunakan dalam kode sumber proyek Anda. Saat ini tidak ada parameter untuk mengatur fungsionalitas ini tetapi akan sepele untuk menambahkan.

Berikut ini contoh sepele:

from pypreprocessor import pypreprocessor

# run the script in 'production' mode
if 'commercial' in sys.argv:
    pypreprocessor.defines.append('commercial')

if 'open' in sys.argv:
    pypreprocessor.defines.append('open')

pypreprocessor.removeMeta = True
pypreprocessor.parse()

Lalu sumbernya:

#ifdef commercial
// Copyright 2012 (C) Acme Technology, All Rights Reserved.
// Very large, often varied and restrictive copyright license in English and French,
// sometimes also embedded in make files and shell scripts with varied 
// comment styles.
#ifdef open
// GPL Copyright (C) Acme Technology Labs 2012, Some rights reserved.
// Acme appreciates your interest in its technology, please contact [email protected] 
// for technical support, and www.acme.com/emergingTech for updates and RSS feed.
#endif

Catatan: Jelas, Anda harus memilah cara untuk mengatur file input / output tetapi itu tidak terlalu sulit.

Pengungkapan: Saya adalah penulis asli pypreprocessor.


Selain itu: Saya awalnya menulisnya sebagai solusi untuk masalah pemeliharaan 2k / 3x python yang ditakuti. Pendekatan saya adalah, lakukan pengembangan 2 dan 3 dalam file sumber yang sama dan hanya menyertakan / mengecualikan perbedaan menggunakan arahan preprocessor. Sayangnya, saya menemukan cara yang sulit bahwa tidak mungkin untuk menulis preprocessor murni murni (yaitu tidak memerlukan c) karena python lexer menandai kesalahan sintaks dalam kode yang tidak kompatibel sebelum preprocessor mendapatkan kesempatan untuk berjalan. Apa pun itu, tetap bermanfaat dalam berbagai keadaan termasuk kondisi Anda.

Evan Plaice
sumber
Batu ini. Jika tidak ada hal lain yang dapat kita lakukan seperti tiga cara diff yang memproses file dengan dan tanpa kode yang ingin kita kecualikan, ambil diff mereka, kemudian hapus garis diffed dari aslinya.
PengembangDon
@ Pengembang Don Yap, itu ide umum. Ada beberapa cara berbeda untuk mengatasinya, itu tergantung pada bagaimana Anda berencana untuk mengelola siklus commit-release. Karya ini hanya mengotomatiskan banyak pekerjaan yang seharusnya membosankan dan / atau rentan kesalahan.
Evan Plaice
1

Mungkin itu ide yang bagus

1. tambahkan tag komentar seperti:

> // *COPYRIGHT-BEGIN-TAG*
> // Copyright 2012 (C) Acme Technology, All Rights Reserved.
> // Very large, often varied and restrictive copyright license in English and French,
> // sometimes also embedded in make files and shell scripts with varied 
> // comment styles. 
> // *COPYRIGHT-ENG-TAG*
>   ... Usual header stuff...
>
> void initTechnologyLibrary() {
>     nuiInterface(on);
> #ifdef  UNDER_RESEARCH
>     holographicVisualization(on);
> #endif
> }

2. Tulis skrip untuk pembuat sumber terbuka untuk memeriksa semua file dan mengganti teks antara tag COPYRIGHT-BEGIN-TAG dan COPYRIGHT-ENG-TAG

Alex Hashimi
sumber
1
Apakah saya perlu tag awal? Sejauh ini semua file sumber kami mulai dengan hak cipta di baris pertama, dan skrip shell kami mulai dengan hak cipta di baris kedua. Ada banyak file, jadi saya ingin melakukan pengeditan tangan sesedikit mungkin.
PengembangDon
Saya pikir beberapa file dapat menggunakan Doxygen untuk menggambarkan fungsi mereka, parameter, dan mengembalikan nama nilai. Untuk file-file yang belum diatur dengan cara itu, itu bisa sangat banyak mengedit jika kita membuat pilihan yang mengambil lebih jauh ke arah itu.
PengembangDon
Setidaknya Anda harus mengubahnya sekali. jika kebijakan hak cipta Anda berubah, Anda dapat mengelolanya.
Alex Hashimi
1

Saya tidak akan menunjukkan kepada Anda alat untuk mengonversi basis kode Anda, banyak jawaban sudah melakukannya. Sebaliknya, saya menjawab komentar Anda tentang cara menangani cabang untuk ini.

Anda harus memiliki 2 cabang:

  • Komunitas (sebut saja versi open source seperti ini)
  • Profesional (sebut saja versi sumber tertutup seperti ini)

Preprosesor seharusnya tidak ada. Anda memiliki dua versi berbeda. Dan basis kode bersih secara keseluruhan.

Anda takut mempertahankan dua salinan secara paralel? Jangan khawatir, Anda bisa bergabung!

Jika Anda membuat modifikasi pada cabang komunitas, gabungkan saja di cabang profesional. Git menangani ini dengan sangat baik.

Dengan cara ini, Anda menyimpan 2 salinan basis kode yang dikelola. Dan melepaskan satu untuk open source semudah pie.

Florian Margaine
sumber