Terakhir diuji pada Ubuntu 20.04 dengan pengembangan glibc versi 2.33.9000 (lihat glibc/version.h
) pada 27 Juni 2021.
Cara mengunduh dan membuat glibc, serta menjalankan tolok ukurnya
Anda dapat memperoleh kode sumber glibc secara manual di sini:https://www.gnu.org/software/libc/sources.html:
git clone https://sourceware.org/git/glibc.git
cd glibc
git checkout master
Cermin pihak ketiga di GitHub:https://github.com/bminor/glibc/tree/master/benchtests
Lihat juga:
- https://kazoo.ga/a-simple-tool-to-test-malloc-performance/
Jika Anda ingin membuat glibc dan uji cobanya secara manual, lakukan sebagai berikut:
# IMPORTANT: begin AT THE SAME DIRECTORY LEVEL as the `glibc` source code
# directory, NOT inside the `glibc` source code dir! In other words, if
# you are in the correct dir, running `ls` will show the `glibc` source
# code dir (that you just cloned) inside the dir you are in.
mkdir -p glibc-build
mkdir -p glibc-install
cd glibc-build
../glibc/configure --prefix="$(realpath "../glibc-install")"
time make -j8 # build with 8 threads (jobs); on a fast laptop this takes ~3 min.
time make install # (optional: install to the `glibc-install` dir you created)
# Build the benchtests (everything inside the `glibc/benchtests` dir) too;
# see the makefile 'glibc/benchtests/Makefile' for more build commands.
time make bench-build -j8
# Now you have this executable file you can use for malloc speed tests, for instance!:
# ../glibc-build/benchtests/bench-malloc-thread
# To build **and run** all glibc benchtests, do:
time make bench
Referensi:
- https://www.gnu.org/software/libc/manual/html_node/Configuring-and-compiling.html
- https://kazoo.ga/a-simple-tool-to-test-malloc-performance/
- https://github.com/f18m/malloc-benchmarks/blob/master/Makefile#L122-L129 :Saya belajar banyak tentang ini dengan mempelajari target makefile ini:
$(glibc_install_dir)/lib/libc.so.6: @echo "Building GNU libc... go get a cup of coffee... this will take time!" mkdir -p $(glibc_build_dir) cd $(glibc_build_dir) && \ ../glibc/configure --prefix=$(glibc_install_dir) && \ make $(parallel_flags) && \ make install [ -x $(glibc_build_dir)/benchtests/bench-malloc-thread ] && echo "GNU libc benchmarking utility is ready!" || echo "Cannot find GNU libc benchmarking utility! Cannot collect benchmark results"
- Bagaimana cara mengkompilasi pustaka standar glibc C saya sendiri dari sumber dan menggunakannya?
Keywords:cara membuat dan menjalankan glibc dan pengujiannya, termasuk. malloc benchtests, dari sumber; membangun glibc dari sumber di linux ubuntu
Makefile
akan ada di build-glibc
Anda direktori jika configure
skrip selesai dengan sukses.
Jika semuanya tampak berjalan lancar selama configure
dan masih belum ada Makefile
, maka Anda mungkin melewatkan keistimewaan:
Saat melakukan configure
untuk glibc, Anda biasanya diharapkan memberikan --prefix
alternatif , karena menginstal ke lokasi default (/usr/local
) berpotensi melumpuhkan sistem. Jika Anda tidak menyediakannya, Anda perlu mengaktifkan --disable-sanity-checks
.
Jika ini juga tidak terjadi, cari config.log
file, dan baca isinya.
Penyiapan 1:glibc tanpa GCC khusus
Penyiapan ini mungkin berhasil dan cepat karena tidak mengkompilasi ulang keseluruhan rantai alat GCC, hanya glibc.
Satu-satunya masalah yang saya miliki dengan penyiapan ini adalah saya belum menemukan cara yang bagus untuk menggunakan objek runtime seperti crt1.o
, crti.o
, dan crtn.o
disediakan oleh glibc kami, dan saya menggunakan yang host untuk saat ini. Ini disebutkan di:https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Objek-objek itu melakukan pengaturan awal yang diandalkan glibc, jadi saya tidak akan terkejut jika semuanya macet dengan luar biasa dan cara yang sangat halus. Lihat upaya penyelesaian ini di bawah.
Bangun glibc dan instal secara lokal:
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.32
mkdir build
cd build
export glibc_install="$(pwd)/install"
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`
Penyiapan 1:verifikasi build
test_glibc.c
#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>
atomic_int acnt;
int cnt;
int f(void* thr_data) {
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
}
return 0;
}
int main(int argc, char **argv) {
/* Basic library version check. */
printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());
/* Exercise thrd_create from -pthread,
* which is not present in glibc 2.27 in Ubuntu 18.04.
* https://stackoverflow.com/questions/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL);
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL);
printf("The atomic counter is %u\n", acnt);
printf("The non-atomic counter is %u\n", cnt);
}
Kompilasi dan jalankan dengan test_glibc.sh
:
#!/usr/bin/env bash
set -eux
gcc \
-L "${glibc_install}/lib" \
-I "${glibc_install}/include" \
-Wl,--rpath="${glibc_install}/lib" \
-Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
-std=c11 \
-o test_glibc.out \
-v \
test_glibc.c \
-pthread \
;
ldd ./test_glibc.out
./test_glibc.out
Perintah diadaptasi dari https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location
Program menampilkan yang diharapkan:
gnu_get_libc_version() = 2.32
The atomic counter is 10000
The non-atomic counter is 8674
ldd
output mengonfirmasi bahwa ldd
dan pustaka yang baru saja kita buat benar-benar digunakan seperti yang diharapkan:
+ ldd test_glibc.out
linux-vdso.so.1 (0x00007ffe4bfd3000)
libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
/home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)
gcc
output debug kompilasi menunjukkan bahwa objek runtime host saya digunakan, yang buruk seperti yang disebutkan sebelumnya, tetapi saya tidak tahu cara mengatasinya, mis. itu berisi:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Penyiapan 1:ubah glibc
Sekarang mari kita ubah glibc dengan:
diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <stdio.h>
+
#include "thrd_priv.h"
int
thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
{
+ puts("hacked");
_Static_assert (sizeof (thr) == sizeof (pthread_t),
"sizeof (thr) != sizeof (pthread_t)");
Kemudian kompilasi ulang dan instal ulang glibc, lalu kompilasi ulang dan jalankan kembali program kami:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
dan kita melihat hacked
dicetak beberapa kali seperti yang diharapkan.
Ini semakin menegaskan bahwa kami benar-benar menggunakan glibc yang kami kompilasi dan bukan host.
Diuji pada Ubuntu 20.10.
Penyiapan 1:mencoba menggunakan crt*
yang benar objek
https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location menyarankan untuk menambahkan --sysroot
ke gcc
perintah tetapi:
- itu tidak benar-benar mengubah objek menjadi milik kita menurut log
- dan itu membuat kompilasi gagal dengan
/usr/bin/ld: cannot find libgcc_s.so.1
mungkin karenasysroot
digunakan untuk objek yang disediakan GCC ini, yang tidak kami miliki di sysroot itu karena kami hanya membangun glibc
Di https://stackoverflow.com/a/66634184/895245 ZeZNiQ memberikan solusi yang mungkin benar, dengan mengirimkan:
-nostartfiles
diikuti oleh semua objek. Anda hanya perlu mengekstrak objek yang benar dari perintah lengkap dengan -nostartfiles
dan meneruskannya secara manual.
Misalnya, di mesin amd64 saya, objek yang digunakan berbeda dari perintah 32-bitnya, jadi ini agak rumit.
Bibliografi:
- Bagaimana cara mengubah direktori pencarian default GCC untuk crti.o?
- https://gcc.gnu.org/legacy-ml/gcc-help/2015-02/msg00016.html
- https://gcc.gnu.org/legacy-ml/gcc-help/2001-11/msg00029.html
Penyiapan 2:penyiapan murni crosstool-NG
Ini adalah alternatif untuk penyiapan 1, dan ini adalah penyiapan paling benar yang telah saya capai sejauh ini:semuanya benar sejauh yang dapat saya amati, termasuk objek runtime C seperti crt1.o
, crti.o
, dan crtn.o
.
Dalam penyiapan ini, kita akan mengompilasi toolchain GCC khusus lengkap yang menggunakan glibc yang kita inginkan.
Satu-satunya downside ke metode ini adalah pembangunan akan memakan waktu lebih lama. Tapi saya tidak akan mengambil risiko penyiapan produksi dengan sesuatu yang kurang dari itu.
crosstool-NG adalah kumpulan skrip yang mengunduh dan mengompilasi semuanya dari sumber untuk kami, termasuk GCC, glibc, dan binutils.
Ya, sistem build GCC sangat buruk sehingga kami memerlukan project terpisah untuk itu.
Penyiapan ini tidak sempurna karena crosstool-NG tidak mendukung pembangunan executable tanpa tambahan -Wl
flags, yang terasa aneh karena kami membuat GCC sendiri. Namun semuanya tampak berfungsi, jadi ini hanyalah ketidaknyamanan.
Dapatkan crosstool-NG, konfigurasikan, dan bangun:
git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
Pembangunan memakan waktu sekitar tiga puluh menit hingga dua jam.
Satu-satunya opsi konfigurasi wajib yang dapat saya lihat adalah membuatnya cocok dengan versi kernel host Anda untuk menggunakan header kernel yang benar. Temukan versi kernel host Anda dengan:
uname -a
yang menunjukkan kepada saya:
4.15.0-34-generic
jadi di menuconfig
Saya lakukan:
Operating System
Version of linux
jadi saya pilih:
4.14.71
yang merupakan versi pertama yang sama atau lebih tua. Itu harus lebih tua karena kernel kompatibel ke belakang.
Penyiapan 2:konfigurasi opsional
.config
yang kami hasilkan dengan ./ct-ng x86_64-unknown-linux-gnu
memiliki:
CT_GLIBC_V_2_27=y
Untuk mengubahnya, di menuconfig
lakukan:
C-library
Version of glibc
simpan .config
, dan lanjutkan dengan pembuatan.
Atau, jika Anda ingin menggunakan sumber glibc Anda sendiri, mis. untuk menggunakan glibc dari git terbaru, lanjutkan seperti ini:
Paths and misc options
Try features marked as EXPERIMENTAL
:disetel ke true
C-library
Source of glibc
Custom location
:katakan yaCustom location
Custom source location
:arahkan ke direktori yang berisi sumber glibc Anda
di mana glibc dikloning sebagai:
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
Penyiapan 2:uji coba
Setelah Anda membuat rantai alat yang Anda inginkan, ujilah dengan:
#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
x86_64-unknown-linux-gnu-gcc \
-Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
-Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
-v \
-o test_glibc.out \
test_glibc.c \
-pthread \
;
ldd test_glibc.out
./test_glibc.out
Segalanya tampak berfungsi seperti pada Penyiapan 1, kecuali bahwa sekarang objek runtime yang benar telah digunakan:
COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o
Penyiapan 2:upaya kompilasi ulang glibc yang gagal
Sepertinya tidak mungkin dengan crosstool-NG, seperti yang dijelaskan di bawah.
Jika Anda baru saja membangun kembali;
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
maka perubahan Anda pada lokasi sumber glibc khusus akan diperhitungkan, tetapi itu membangun semuanya dari awal, sehingga tidak dapat digunakan untuk pengembangan berulang.
Jika kita melakukannya:
./ct-ng list-steps
ini memberikan ikhtisar yang bagus tentang langkah-langkah pembuatan:
Available build steps, in order:
- companion_tools_for_build
- companion_libs_for_build
- binutils_for_build
- companion_tools_for_host
- companion_libs_for_host
- binutils_for_host
- cc_core_pass_1
- kernel_headers
- libc_start_files
- cc_core_pass_2
- libc
- cc_for_build
- cc_for_host
- libc_post_cc
- companion_libs_for_target
- binutils_for_target
- debug
- test_suite
- finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.
oleh karena itu, kami melihat bahwa ada langkah-langkah glibc yang terkait dengan beberapa langkah GCC, terutama libc_start_files
datang sebelum cc_core_pass_2
, yang mungkin merupakan langkah termahal bersama dengan cc_core_pass_1
.
Untuk membuat satu langkah saja, Anda harus menyetel terlebih dahulu "Simpan langkah perantara" di .config
opsi untuk build awal:
Paths and misc options
Debug crosstool-NG
Save intermediate steps
lalu Anda dapat mencoba:
env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`
tapi sayangnya, +
diperlukan sebagaimana disebutkan di:https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536
Namun perlu dicatat bahwa memulai ulang pada langkah menengah akan menyetel ulang direktori instalasi ke status yang dimilikinya selama langkah tersebut. Yaitu, Anda akan memiliki libc yang dibangun kembali - tetapi tidak ada kompiler final yang dibuat dengan libc ini (dan karenanya, tidak ada pustaka kompiler seperti libstdc++ juga).
dan pada dasarnya masih membuat pembangunan kembali terlalu lambat untuk dapat dikembangkan, dan saya tidak melihat cara mengatasinya tanpa menambal crosstool-NG.
Selanjutnya mulai dari libc
step sepertinya tidak menyalin sumber lagi dari Custom source location
, selanjutnya membuat metode ini tidak dapat digunakan.
Bonus:stdlibc++
Bonus jika Anda juga tertarik dengan pustaka standar C++:Bagaimana cara mengedit dan membuat ulang sumber pustaka standar GCC libstdc++ C++?
Menambahkan ke jawaban/solusi Ciro sebelumnya https://stackoverflow.com/a/52454710/4726668 :
@CiroSantilli Mengedit jawaban Anda mengembalikan "Antrean edit yang disarankan sudah penuh". Skrip ldd yang Anda panggil di test_glibc.sh
skrip menunjuk ke linker dinamis host:/home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)
. Untuk memperbaikinya, di test_glibc.sh
, ubah ldd
ke ${glibc_install}/bin/ldd
. Ini akan mengharuskan Anda untuk menambahkan crt
bawaan *.o juga ke skrip:
-nostartfiles \
${glibc_install}/lib/crti.o \
${glibc_install}/lib/crtn.o \
${glibc_install}/lib/crt1.o \
Di mesin GNU/Linux i386/i686 (32-bit x86 arch), berikut adalah test_glibc.sh
saya yang berfungsi :
#!/usr/bin/env bash
set -eux
gcc \
-L "${glibc_install}/lib" \
-I "${glibc_install}/include" \
-Wl,--rpath="${glibc_install}/lib" \
-Wl,--dynamic-linker="${glibc_install}/lib/ld-linux.so.2" \
-std=c11 \
-nostartfiles \
${glibc_install}/lib/crti.o \
${glibc_install}/lib/crtn.o \
${glibc_install}/lib/crt1.o \
-o test_glibc.out \
-v \
test_glibc.c \
-pthread \
;
${glibc_install}/bin/ldd ./test_glibc.out
./test_glibc.out