LLVMとclangを使ってC++を実行時にコンパイルする方法を解説します
libdcompileNaomasa Matsubayashi
View Slide
@fadis_࠷ۙͷ"ࣾ$7JN(FOUPPมଶΛࣝผ͢Δཁૉ
int main() {!float a = 5.0f;!std::vector< boost::filesystem::path > f;!f.push_back( "hoge.cpp" );!f.push_back( "fuga.cpp" );!dcompile::dynamic_compiler dc;!dc.getLoader().enableSystemPath();!if( !dc.getLoader().load( "jpeg" ) )!throw Ouch();!dc.getHeaderPath().enableSystemPath();!dcompile::module lib = dc( f.begin(), f.end() );!boost::optional< dcompile::function > foo =!lib.getFunction( "foo" );!if( foo )!(*foo)( &a );!else!throw Ouch();!std::cout << a << " outside" << std::endl;!}
$ʹແͯ͘൵͍͠ͷFWBM
FWBMͱ1FSMͷ߹FWBMQSJOUa)FMMP 8PSMEaOa͔͜͜Β ͜͜·ͰจࣈྻจࣈྻͰ༩͑ΒΕͨίʔυΛ࣮ߦ͢Δ
FWBMͱจࣈྻͰ༩͑ΒΕͨίʔυΛ࣮ߦ͢Δ@45%*/FWBM@ਖ਼͍͠DBUIPHFQM@45%*/FWBM@FDIPQSJOU)FMMP 8PSMEaOcQFSMIPHFQM)FMMP 8PSME
FWBMͱDBUIPHFQM@45%*/FWBM@FDIPQSJOU)FMMP 8PSMEaOcQFSMIPHFQM)FMMP 8PSMEॲཧ༰͕QSJOUʹܾ·ͬͨͷ࣮ߦ࣮࣌ߦ࣌ʹίʔυΛղऍͯ͠Ϛγϯޠʹམͱ͢खஈ͕ඞཁ
FWBMͱ࣮ߦ࣌ʹίʔυΛղऍͯ͠Ϛγϯޠʹམͱ͢खஈ͕ඞཁ1FSM 0, 3VCZ 0,1ZUIPO 0, +BWB4DSJQU 0,$ PS[ $ PS[% ίϯύΠϧ࣌ͷΈ +BWB PS[$ 0, )BTLFMM 0,ίϯύΠϥ͕ϥΠϒϥʹؚ·Ε͍ͯΔ
ϥΠϒϥϦʹͳͬͯΔ$ίϯύΠϥ--7.DMBOH͜ΕΛ͑$ͰFWBMͰ͖Δͣ
MJCEDPNQJMFIUUQTHJUIVCDPN'BEJTMJCEDPNQJMF
ϚγϯޠϚγϯޠͷੜDMBOH --7.VTFS$#$$#$ߏจղੳ#$*3ϦϯΫ
--7.ಡΈࠐΜͩ#$ͷѻ͍Λछྨ͔ΒબΔίϯύΠϧϚγϯޠʹมͯ݁͠ՌΛϑΝΠϧʹॻ͖ग़͢ΠϯλϓϦλ ߦͮͭಡΈࠐΜͰ࣮ߦ+*5ίϯύΠϧඞཁ࠷খݶͷ෦͚ͩΛίϯύΠϧ͠ͳ͕Β࣮ߦ௨ৗ$ͷίʔυΛίϯύΠϧ͢Δ߹ʮίϯύΠϧʯ͕༻͍ΒΕΔ
FWBMΛ͢Δ߹ίϯύΠϧΛ͖͢Ͱͳ͍--7.ʹ&-'ͱ͔1&ͱ͔Λѻ͑ΔϦϯΧ͕ͳ͍3FRVJSFNFOU(/6CJOVUJMTͱ͔ͯͳ͍͠ίϯύΠϧҎ֎ͷํ๏Ͱ࣮ߦ͢ΔͱෆࢥٞͳྗʹΑΓԿࣄແ࣮͘ߦग़དྷΔ
ϦϯΧΛΘͣʹͲ͏ͬͯґଘϥΠϒϥϦΛϦϯΫ͍ͯ͠Δͷ͔--7.ΠϯλϓϦλ+*5Ͱ࣮ߦ͢ΔࡍಉҰ#$தʹݟ͔ͭΒͳ͍γϯϘϧΛEMGDOͰ୳ͦ͏ͱ͢ΔάϩʔόϧมJOUBίϯύΠϧ࣌ίϯύΠϧJODMVEFJPTUFSBNFYUFSOJOUBJOUNBJO \TUEDPVUBTUEFOEM^࣮ߦ࣌ίϯύΠϧݟ͑Δʂ
--7.ΠϯλϓϦλ+*5Ͱ࣮ߦ͢ΔࡍಉҰ--7.*3தʹݟ͔ͭΒͳ͍γϯϘϧΛEMGDOͰ୳ͦ͏ͱ͢ΔϦϯΧΛΘͣʹͲ͏ͬͯґଘϥΠϒϥϦΛϦϯΫ͍ͯ͠Δͷ͔EMGDOͰݟ͔ͭΔͷݩʑόΠφϦதʹ͋ͬͨγϯϘϧ35%-@(-0#"-Ͱϩʔυͨ͠γϯϘϧ͋Β͔͡ΊඞཁͳϥΠϒϥϦΛEMPQFOͯ͋͠Δͱ࣮ߦ࣌ʹίϯύΠϧ͞ΕΔίʔυͷத͔ΒͦͷϥΠϒϥϦͷ͕ؔԿͱͳ͘ݺΔ
ϦϯΧΛΘͣʹͲ͏ͬͯґଘϥΠϒϥϦΛϦϯΫ͍ͯ͠Δͷ͔EMGDO104*9ݻ༗--7.ʹγεςϜͷμΠφϛοΫϩʔυΛநԽ͕ͨؔ͠༻ҙ͞Ε͍ͯΔͨͩ͠ϩʔυ͚ͩMMWNTZT%ZOBNJD-JCSBSZ-PBE-JCSBSZ1FSNBOFOUMZ
ϦϯΧΛΘͣʹͲ͏ͬͯґଘϥΠϒϥϦΛϦϯΫ͍ͯ͠Δͷ͔JODMVEFKQFHMJCIJOUNBJO \TUSVDUKQFH@DPNQSFTT@TUSVDUDJOGPKQFH@DSFBUF@DPNQSFTT DJOGP^MJCKQFH͕ཁΔ࣮ߦ։࢝MJCKQFHΛμΠφϛοΫϩʔυࠨ্ͷίʔυΛ+*5ίϯύΠϧ͜ͷ࣌ͰEMGDO͔Βݟ͑Δͱ͜ΖʹMJCKQFHͷγϯϘϧ͕͋ΔͷͰԿࣄແ͔͔ͬͨͷΑ͏ʹ࣮ߦग़དྷΔ
int main() {!float a = 5.0f;!std::vector< boost::filesystem::path > f;!f.push_back( "hoge.cpp" );!f.push_back( "fuga.cpp" );!dcompile::dynamic_compiler dc;!dc.getLoader().enableSystemPath();!if( !dc.getLoader().load( "jpeg" ) )!throw Ouch();!dc.getHeaderPath().enableSystemPath();!dcompile::module lib = dc( f.begin(), f.end() );!boost::optional< dcompile::function > foo =!lib.getFunction( "foo" );!if( foo )!(*foo)( &a );!else!throw Ouch();!std::cout << a << " outside" << std::endl;!}f.push_back( "hoge.cpp" );!f.push_back( "fuga.cpp" );dcompile::dynamic_compiler dc;dc.getLoader().enableSystemPath();!if(!!dc.getLoader().load( "jpeg" ) )!throw Ouch();dc.getHeaderPath()!.enableSystemPath();dcompile::module lib =!dc( f.begin(), f.end() );boost::optionaldcompile::function!> foo = lib.getFunction( "foo" );(*foo)( &a );
#include !extern "C" void moo( float *a );!extern "C" void foo( float *a ) {!struct jpeg_compress_struct cinfo;!jpeg_create_compress( &cinfo );!moo( a );!}#include !extern "C"!void moo( float *a ) {!std::cout << *a << " inslide" << std::endl;!std::cout << "Hello, world!" << std::endl;!*a += 0.1f;!}IPHFDQQGVHBDQQ
ಉҰϓϩηεϗετίʔυMJCKQFHNBJOqPBUBIPHFDQQGPPGVHBDQQNPPॲཧͷྲྀΕJOTMJEF)FMMP XPSMEPVUTJEFͳΜ͔૿͑ͯΔ
%ͳΜͱ͔͞Μ͕࡞ͬͨ#0045@11ͩΒ͚ͷίʔυதͳΜͱ͔͞Μ͕࡞ͬͨDPOTUFYQSͩΒ͚ͷίʔυ࣮ߦ࣌ʹ࣮ߦग़དྷΔʂ͍͢͝ʂ࠷ॳ͔Β࣮ߦ࣌ʹॲཧ͢ΔΑ͏ʹॻ͚ʂ
DMBOHͷา͖ํDMBOHͷιʔεʹؔ͢Δ࠷ݶͷυΩϡϝϯτͦΕEPYZHFODMBOHͷιʔεʹؔ͢ΔৄࡉͳυΩϡϝϯτͦΕιʔεΘ͔Βͳ͍͜ͱιʔεʹฉ͚
DMBOHͷา͖ํ--7.ͱDMBOHͷࠓ͕Θ͔ΔߪಡແྉHJUDMPOFIUUQMMWNPSHHJUMMWNHJUDEMMWNUPPMTHJUDMPOFIUUQMMWNPSHHJUDMBOHHJUࠓ͙͢DMPOF
DMBOHͷา͖ํͰɺͲ͔͜ΒಡΊྑ͍ͷNBJO͔ؔΒͩΖKL0XOJOH1US$PNQJMBUJPO$ 5IF%SJWFS#VJME$PNQJMBUJPO BSHWJOU3FTDPOTU$PNNBOE'BJMJOH$PNNBOEJG $HFU 3FT5IF%SJWFS&YFDVUF$PNQJMBUJPO $ 'BJMJOH$PNNBOE --7.@4063$&@%*3UPPMTDMBOHUPPMTESJWFSESJWFSDQQDMBOHίϚϯυͷNBJOؔͷࡏॲߦ͋ͨΓ͔ΒNBJO
DMBOHͷา͖ํJOU3FT$&YFDVUF+PC $HFU+PCT 'BJMJOH$PNNBOE --7.@4063$&@%*3UPPMTDMBOHMJC%SJWFS%SJWFSDQQߦ͋ͨΓ͔Β&YFDVUF$PNQJMBUJPO --7.@4063$&@%*3UPPMTDMBOHMJC%SJWFS$PNQJMBUJPODQQߦ͋ͨΓ͔Β&YVFDVUF+PCMMWNTZT1SPHSBN&YFDVUF"OE8BJU 1SPH "SHW FOW 3FEJSFDUT TFDPOET5P8BJU NFNPSZ-JNJU &SSPSॲཧͷஈ֊ຖʹׂͯ͠DMBOHΛݺͼ͢
DMBOHͷา͖ํJG BSHWTJ[F 4USJOH3FG BSHW<>TUBSUTXJUI DD\4USJOH3FG5PPMBSHW<>!JG 5PPMSFUVSODD@NBJO BSHWEBUB BSHWEBUB BSHWTJ[F BSHW<> WPJE JOUQUS@U(FU&YFDVUBCMF1BUIJG 5PPMBTSFUVSODDBT@NBJO BSHWEBUB BSHWEBUB BSHWTJ[F BSHW<> WPJE JOUQUS@U(FU&YFDVUBCMF1BUI!3FKFDUVOLOPXOUPPMTMMWNFSST FSSPSVOLOPXOJOUFHSBUFEUPPM5PPMaOSFUVSO^ --7.@4063$&@%*3UPPMTDMBOHUPPMTESJWFSESJWFSDQQߦ͋ͨΓ͔ΒNBJO
DMBOHͷา͖ํMMWN*OJUJBMJ[F"MM5BSHFUT MMWN*OJUJBMJ[F"MM5BSHFU.$T MMWN*OJUJBMJ[F"MM"TN1SJOUFST MMWN*OJUJBMJ[F"MM"TN1BSTFST --7.@4063$&@%*3UPPMTDMBOHUPPMTESJWFSDD@NBJODQQߦ͋ͨΓ͔ΒDD@NBJOMMWNͷ͍͍ՃݮͳॳظԽ4VDDFTT&YFDVUF$PNQJMFS*OWPDBUJPO $MBOHHFU --7.@4063$&@%*3UPPMTDMBOHMJC'SPOUFOE5PPM&YFDVUF$PNQJMFS*OWPDBUJPODQQbool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {ߦ͋ͨΓ͔Β&YFDVUF$PNQJMFS*OWPDBUJPO
DMBOHͷา͖ํॏཁΫϥε$PNQJMFS*OTUBODF$PNQJMFS*OTUBOD'JMF.BOBHFS4PVSDF.BOBHFS%JBHOPTUJDT "DUJPO5BSHFU0QUJPO
DMBOHͷา͖ํॏཁΫϥε$PNQJMFS*OTUBODFSuccess = Clang->ExecuteAction(*Act); --7.@4063$&@%*3UPPMTDMBOHMJC'SPOUFOE5PPM&YFDVUF$PNQJMFS*OWPDBUJPODQQߦ͋ͨΓ͔Β&YFDVUF$PNQJMFS*OWPDBUJPOOwningPtr Act(CreateFrontendAction(*Clang));"DUJPOΛ$PNQJMFS*OTUBODFʹͯ͠&YFDVUF"DUJPO͢Δ$PNQJMFS*OTUBODF͕ύʔαΛݺͼग़͠ߏจղੳͷ݁Ռݟ͔ͭͬͨཁૉʹԠͯ͡"DUJPOͷରԠ͢Δϝϯό͕ؔݺΕΔ
DMBOHͷา͖ํ࠷ॳ͔Β༻ҙ͞Ε͍ͯΔΞΫγϣϯ&NJU"TTFNCMZ"DUJPO &NJU#$"DUJPO&NJU--7."DUJPO &NJU--7.0OMZ"DUJPO&NJU$PEF(FO0OMZ"DUJPO&NJU0CK"DUJPO0CK·Ͱ͍࣋ͬͯͬͯ͠·͏ͱϦϯΫग़དྷͳͯ͘٧Ή
--7.ͷา͖ํෳͷ--7.Ϟδϡʔϧ CDͱ͔͍ͭͯΔͭΛͭͷ--7.Ϟδϡʔϧʹ·ͱΊΔ--7.-JOLFSʹ͞ΕͨϞδϡʔϧ--7.-JOLFS͕ղ์͢Δ--7.-JOLFS͕࡞ͬͨϞδϡʔϧ໌ࣔతʹࢦఆ͠ͳ͍ͱ--7.-JOLFS͕ղ์͢Δ#$#$#$ϦϯΫ
--7.ͷา͖ํग़དྷ্͕ͬͨϞδϡʔϧͲ͏࣮ͬͯߦ͢Ε͍͍ͷιʔεʹฉ͚ʂ --7.@4063$&@%*3UPPMTMMJMMJDQQߦ͋ͨΓ͔ΒNBJO*OJUJBMJ[F/BUJWF5BSHFU *OJUJBMJ[F/BUJWF5BSHFU"TN1SJOUFS ωΠςΟϒλʔήοτͷॳظԽ
--7.ͷา͖ํϞδϡʔϧΛ&OHJOF#VJMEFSʹ͠λʔήοτΛࢦఆͯ͠ΠϯλϓϦλ࣮ߦ͔+*5ίϯύΠϧ͔બͼ&YFDVUJPO&OHJOFΛੜ͢Δ&OHJOF#VJMEFSCVJMEFS .PECVJMEFSTFU."SDI ."SDICVJMEFSTFU.$16 .$16CVJMEFSTFU."UUST ."UUSTCVJMEFSTFU6TF.$+*5 USVF&&CVJMEFSDSFBUF
--7.ͷา͖ํ&&SVO4UBUJD$POTUSVDUPST%FTUSVDUPST GBMTFϞδϡʔϧͷίϯετϥΫλΛ࣮ߦJOU3FTVMU&&SVO'VODUJPO"T.BJO &OUSZ'O *OQVU"SHW FOWQࢦఆͨؔ͠ΛNBJOؔͱݟͳ࣮ͯ͠ߦࣗͰҾΛਖ਼͘͠ઃఆ͢ΕNBJOؔͱܕͷҧ͏͔ؔΒ࣮ߦ͢Δ͜ͱՄೳ(FOFSJD7BMVF3FTVMUFOHJOFSVO'VODUJPO &OUSZ'O "SHT&&SVO4UBUJD$POTUSVDUPST%FTUSVDUPST USVFϞδϡʔϧͷσετϥΫλΛ࣮ߦ
MJCDMBOHʹ͍ͭͯDMBOHͷϥΠϒϥϦͬͯࠓྲྀߦͷMJCDMBOH͕͍ͪ·͢DMBOHͷϥΠϒϥϦ܉ஂMJCDMBOH"3$.JHSBUFMJCDMBOH"45BMJCDMBOH"OBMZTJTBMJCDMBOH#BTJDBMJCDMBOH$PEF(FOBMJCDMBOH%SJWFSBMJCDMBOHTPDMBOHͷϥΠϒϥϦΛ$ݴޠΠϯλʔϑΣʔεͰϥοϓͨ͠ͷ
MJCDMBOHʹ͍ͭͯMJCDMBOH͞ΜߏจղੳΛߦ͏ͱ͜Ζ·Ͱ͔͠ϥοϓ͍ͯ͠ͳ͍MJCDMBOHͰݡ͍γϯλοΫεͱ͔͋ͬͯMJCDMBOHͰίϯύΠϧͱ͔ฉ͔ͳ͍ͷͦͷͨΊ$FSϥούΛհ͞ͳͯ͘શͯͷϥΠϒϥϦΛར༻Ͱ͖ΔMJCDMBOHͱ͔͍ΒΜ͔ͬͨΜʂ $FSʹݶΔ
ϦϯΫ͖͢ϥΠϒϥϦ2DMBOHͱ--7.ͷϥΠϒϥϦࢁ͋Γ·͕͢ɺࣗͷίʔυΛಈ͔ͨ͢ΊʹඞཁͳͷͲΕͱͲΕͰ͠ΐ͏ͲͷγϯϘϧ͕ͲͷϥΠϒϥϦʹؚ·Ε͍ͯΔ͔Ͳ͜ʹॻ͔Ε͍ͯͳ͍"શ෦ϦϯΫ͔ͯ͠Βͭͮͭ֎ͯ͠ΈͯɺϦϯΫΤϥʔ͕ग़ΔϠπͬͯΔʂ
ϦϯΫ͖͢ϥΠϒϥϦMJCDMBOH"3$.JHSBUF MJCDMBOH"45B MJCDMBOH"OBMZTJTBMJCDMBOH#BTJDB MJCDMBOH$PEF(FOB MJCDMBOH%SJWFSBMJCDMBOH&EJUB MJCDMBOH'SPOU&OEB MJCDMBOH'SPOU&OE5PPMMJCDMBOH*OEFYB MJCDMBOH-FYB MJCDMBOH1BSTFBMJCDMBOH3FXSJUFB MJCDMBOH4FNBB MJCDMBOH4FSJBMJ[BUJPOMJC--7."TN1BSTFSB MJC--7."TN1SJOUFSB MJC--7.#JU3FBEFSBMJC--7.&YFDVUJPO&OHJOF MJC--7.+*5B MJC--7..$+*5BMJC--7.$PEF(FOB MJC--7.JQPB MJC--7.$PSFBMJC--7.-JOLFSB MJC--7.*OTUSVNFOUBUJPOBMJCEDPNQJMFͷ߹
ݱ࣌Ͱͷ՝࣮ߦ࣌ίϯύΠϧ͞Εͨίʔυͷؔݺͼग़࣌͠ҾͷੵΈํ͕ಾݱঢ়όΠτҎԼͷQPEܕ͔ͤ͠ͳ͍ϓϦϓϩηοαεςʔδͷΈ࣮ߦ͕Ͱ͖ͳ͍ݱࡏ࣮࡞ۀத--7.ͷόʔδϣϯ্͕͕ΔͨͼʹΠϯλʔϑΣʔε͕มΘΔ
݁$Ͱ࣮ߦ࣌ίϯύΠϧͰ͖Δ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠