সেটআপ 1: উত্সর্গীকৃত জিসিসি ছাড়াই আপনার নিজের গ্লিবসি সংকলন করুন এবং এটি ব্যবহার করুন
যেহেতু কেবল প্রতীক সংস্করণ হ্যাকগুলি দিয়ে কাজ করা অসম্ভব বলে মনে হচ্ছে, তাই আসুন আমরা আরও এক ধাপ এগিয়ে যাই এবং গ্লিবিসিটি নিজেরাই সংকল করি।
এই সেটআপটি কার্যকর হতে পারে এবং দ্রুত হয় কারণ এটি পুরো গিসি সরঞ্জাম সরঞ্জামটি পুনরায় সংশ্লেষ করে না, কেবল গ্লিবসি।
কিন্তু এটা নির্ভরযোগ্য হিসাবে এটি ব্যবহার করে হোস্ট সি রানটাইম যেমন বস্তু হিসেবে নয় crt1.o
, crti.o
এবং crtn.o
জন্য glibc দ্বারা উপলব্ধ। এটিতে এখানে উল্লেখ করা হয়েছে: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location এই বিষয়গুলি প্রাথমিকভাবে সেটআপ করে যা গ্লিবসি নির্ভর করে, তাই আমি বিস্মিত হবো না যদি জিনিসগুলি বিস্ময়করভাবে ক্র্যাশ হয়ে যায় I এবং দুর্দান্তভাবে সূক্ষ্ম উপায়।
আরও নির্ভরযোগ্য সেটআপের জন্য, নীচে সেটআপ 2 দেখুন।
গ্লিবসি তৈরি করুন এবং স্থানীয়ভাবে ইনস্টল করুন:
export glibc_install="$(pwd)/glibc/build/install"
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`
সেটআপ 1: বিল্ডটি যাচাই করুন
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.
* /programming/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);
}
সংকলন এবং এর সাথে চালান 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
প্রোগ্রামটি প্রত্যাশিত ফলাফলগুলি প্রকাশ করে:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location থেকে কমান্ডটি অভিযোজিত হয়েছে তবে এতে --sysroot
এটি ব্যর্থ হয়েছে:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
সুতরাং আমি এটি সরিয়েছি।
ldd
আউটপুট নিশ্চিত ldd
করে যে আমরা যে লাইব্রেরিগুলি তৈরি করেছিলাম তা বাস্তবে প্রত্যাশার মতো ব্যবহৃত হচ্ছে:
+ 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
সংকলন ডিবাগ আউটপুট শো যে আমার হোস্ট রানটাইম বস্তু ব্যবহার করা হয়, যা খারাপ পূর্বে উল্লিখিত, কিন্তু আমি কিভাবে এটা কাজ করে জানি না হয়, যেমন এটা রয়েছে:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
সেটআপ 1: গ্লিবসি পরিবর্তন করুন
এখন এর সাথে গ্লিবসি পরিবর্তন করুন:
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)");
তারপরে পুনরায় সংকলন এবং গ্লিব্যাক পুনরায় ইনস্টল করুন, এবং আমাদের প্রোগ্রামটি পুনরায় সংকলন এবং পুনরায় চালনা করুন:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
এবং আমরা hacked
প্রত্যাশিত হিসাবে কয়েকবার মুদ্রিত দেখতে পাই ।
এটি আরও নিশ্চিত করে যে আমরা প্রকৃতপক্ষে হোস্টটি নয়, যে সংকলনটি সঙ্কলন করেছি তা ব্যবহার করেছি।
উবুন্টু 18.04 এ পরীক্ষিত।
2 সেটআপ: ক্রসস্টুল-এনজি মূল সেটআপ
এই সেটআপ 1 বিকল্প, এবং এটা সবচেয়ে সঠিক সেটআপ আমি এ পর্যন্ত অর্জন করেছি হল: সবকিছু যতটা সঠিক হিসাবে আমি অন্তর্গত সি রানটাইম যেমন বস্তু, মান্য করতে পারেন crt1.o
, crti.o
এবং crtn.o
।
এই সেটআপে, আমরা একটি সম্পূর্ণ ডেডিকেটেড জিসিসি টুলচেইন সংকলন করব যা আমাদের চাই গ্লিবিসি ব্যবহার করে।
এই পদ্ধতির একমাত্র ক্ষতিটি হ'ল বিল্ডটি আরও বেশি সময় নেবে। তবে আমি কম কিছু দিয়ে একটি প্রোডাক্ট সেটআপ ঝুঁকি নেব না।
ক্রসস্টুল-এনজি হ'ল স্ক্রিপ্টগুলির একটি সেট যা জিসিসি, গ্লিবিসি এবং বাইনুটিলস সহ আমাদের জন্য উত্স থেকে সমস্ত কিছু ডাউনলোড এবং সংকলন করে।
হ্যাঁ জিসিসি বিল্ড সিস্টেমটি এত খারাপ যে এর জন্য আমাদের একটি পৃথক প্রকল্পের প্রয়োজন।
এই সেটআপটি কেবল সঠিক নয় কারণ ক্রসস্টুল-এনজি অতিরিক্ত -Wl
পতাকা ছাড়াই এক্সিকিউটেবলগুলি তৈরির পক্ষে সমর্থন করে না , যা আমরা নিজেই জিসিসি তৈরি করেছি বলেই অদ্ভুত বোধ করে। তবে সবকিছু কাজ করে বলে মনে হচ্ছে, সুতরাং এটি কেবল কোনও অসুবিধা।
ক্রসস্টুল-এনজি পান এবং এটি কনফিগার করুন:
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
একমাত্র বাধ্যতামূলক বিকল্প যা আমি দেখতে পাচ্ছি, এটি সঠিক হোস্টেল কার্নেল শিরোনামগুলি ব্যবহার করতে আপনার হোস্ট কার্নেল সংস্করণের সাথে মেলে। এর সাথে আপনার হোস্ট কার্নেলের সংস্করণটি সন্ধান করুন:
uname -a
যা আমাকে দেখায়:
4.15.0-34-generic
তাই menuconfig
আমি কি:
সুতরাং আমি নির্বাচন করুন:
4.14.71
এটি প্রথম সমান বা পুরানো সংস্করণ। কার্নেলটি পিছনের দিকে সামঞ্জস্যপূর্ণ হওয়ার কারণে এটি আরও পুরানো হতে হবে।
এখন আপনি এটি দিয়ে তৈরি করতে পারেন:
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
এবং এখন সংকলনের জন্য প্রায় ত্রিশ মিনিট থেকে দুই ঘন্টা অপেক্ষা করুন।
সেটআপ 2: .চ্ছিক কনফিগারেশন
.config
আমরা উত্পন্ন যে ./ct-ng x86_64-unknown-linux-gnu
আছে:
CT_GLIBC_V_2_27=y
এটি পরিবর্তন করতে, menuconfig
করণীয়:
C-library
Version of glibc
সংরক্ষণ করুন .config
এবং বিল্ডটি দিয়ে চালিয়ে যান।
অথবা, যদি আপনি নিজের গ্লিবসি উত্সটি ব্যবহার করতে চান, যেমন সর্বশেষতম গিট থেকে গ্লিবিসি ব্যবহার করতে, এভাবে এগিয়ে যান :
Paths and misc options
Try features marked as EXPERIMENTAL
: সত্য হিসাবে সেট করা
C-library
Source of glibc
Custom location
: হ্যাঁ বলুন
Custom location
Custom source location
: আপনার glibc উত্স ধারণকারী ডিরেক্টরিতে নির্দেশ করুন
যেখানে glibc হিসাবে ক্লোন করা হয়েছিল:
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
সেটআপ 2: এটি পরীক্ষা করে দেখুন
একবার আপনি যে সরঞ্জামটি চান তা বানিয়ে ফেললে এটি পরীক্ষা করে দেখুন:
#!/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
সবকিছুই সেটআপ 1-তে কাজ করছে বলে মনে হয়, এখন বাদে সঠিক রানটাইম অবজেক্টগুলি ব্যবহৃত হয়েছিল:
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
সেটআপ 2: দক্ষ গ্লিবসি পুনঃসংশোধনের প্রচেষ্টা ব্যর্থ হয়েছে
এটি নীচে বর্ণিত হিসাবে ক্রসস্টুল-এনজি দিয়ে সম্ভব বলে মনে হচ্ছে না।
আপনি যদি কেবল পুনর্নির্মাণ করেন;
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
তারপরে কাস্টম গ্লিবিসি উত্সের অবস্থানের আপনার পরিবর্তনগুলি বিবেচনায় নেওয়া হয় তবে এটি স্ক্র্যাচ থেকে সবকিছু তৈরি করে, এটি পুনরুক্তি বিকাশের জন্য অকেজো করে তোলে।
আমরা যদি:
./ct-ng list-steps
এটি বিল্ড স্টেপগুলির একটি সুন্দর ওভারভিউ দেয়:
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.
অতএব, আমরা দেখতে পাই যে বেশ কয়েকটি জিসিসি পদক্ষেপের সাথে জড়িত গ্লিবসি পদক্ষেপ রয়েছে, বিশেষত উল্লেখযোগ্যভাবে libc_start_files
আগে চলে আসে cc_core_pass_2
, এটি সম্ভবত সবচেয়ে ব্যয়বহুল পদক্ষেপ এক সাথে হয় cc_core_pass_1
।
মাত্র এক ধাপ তৈরি করতে, আপনাকে প্রথমে .config
অন্তর্নির্মিত বিল্ডের বিকল্পটিতে "মধ্যবর্তী পদক্ষেপগুলি সংরক্ষণ করুন" সেট করতে হবে :
এবং তারপরে আপনি চেষ্টা করতে পারেন:
env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`
কিন্তু দুর্ভাগ্যক্রমে, এখানে +
উল্লিখিত হিসাবে প্রয়োজনীয়: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536
তবে নোট করুন যে একটি মধ্যবর্তী পদক্ষেপে পুনরায় আরম্ভ করার পরে ইনস্টলেশন ডিরেক্টরিটি সেই পদক্ষেপের সময় থাকা অবস্থায় পুনরায় সেট করে। অর্থাত্, আপনার একটি পুনর্নির্মাণ libc থাকবে - তবে এই libc দিয়ে কোনও চূড়ান্ত সংকলক নির্মিত হয়নি (এবং অতএব, libstdc ++ এর মতো কোনও সংকলক লাইব্রেরি নেই)।
এবং মূলত এখনও পুনর্নির্মাণটি বিকাশের পক্ষে কার্যকর হতে ধীর করে তোলে এবং ক্রসস্টুল-এনজি প্যাচ না করে কীভাবে এটি পরাভূত হবে তা আমি দেখতে পাই না।
তদ্ব্যতীত, libc
পদক্ষেপটি থেকে শুরু করে উত্স থেকে আর অনুলিপি করা হয়নি বলে মনে হয় Custom source location
, আরও এই পদ্ধতিটি অকেজো করে তোলে।
বোনাস: stdlibc ++
আপনি যদি সি ++ স্ট্যান্ডার্ড লাইব্রেরিতে আগ্রহী হন তবে একটি বোনাস: কীভাবে সম্পাদনা করবেন এবং জিসিসি libstdc ++ C ++ স্ট্যান্ডার্ড লাইব্রেরি উত্সটি পুনর্নির্মাণ করবেন?