実現したいこと
エラーが発生しないようにする
前提
Windows10 MSYS2
あるコードの一部に使う1文字ずつ出力する仕組みにICUを使ってみようと思い、ChatGPTにコードを生成してもらいました
コンパイルにはg++ (Rev2, Built by MSYS2 project) 13.2.0とmakeを使用しています
ICUの.libファイル(icuin.lib icuio.lib icutest.lib icutu.lib icuuc.lib)はc:/msys64/mingw64/libに置いています
.hファイルはc:/msys64/mingw64/include/unicodeに置いています
cd C:/CPP make -B -f C:/CPP/_.mk
c:/msys64/mingw64/bin/g++ -fexec-charset=cp932 -Ic:/msys64/mingw64/include -c test.cpp c:/msys64/mingw64/bin/g++ -o test.exe test.o -Lc:/msys64/mingw64/lib -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licudt.lib: No such file or directory C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licuin.lib: No such file or directory C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licuio.lib: No such file or directory C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licutest.lib: No such file or directory C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licutu.lib: No such file or directory C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : cannot find -licuuc.lib: No such file or directory
該当のソースコード
C++(c:/cpp/test.cpp)
1#include <iostream> 2#include <string> 3#include <unicode/unistr.h> 4#include <unicode/ustream.h> 5#include <unicode/uchar.h> 6 7int main() { 8 // 入力文字列 9 std::string inputText = "Hello 世界"; 10 11 // UTF-8からUnicodeStringに変換 12 icu::UnicodeString unicodeStr = icu::UnicodeString::fromUTF8(inputText.c_str()); 13 14 // イテレータを使用して1文字ずつ出力 15 UChar32 c; 16 for (int32_t i = 0; i < unicodeStr.length(); i += U16_LENGTH(c)) { 17 c = unicodeStr.char32At(i); 18 std::cout << "Character: " << c << std::endl; 19 } 20 21 return 0; 22} 23
makefile(c:/cpp/_.mk)
1CC = c:/msys64/mingw64/bin/g++ 2CFLAGS = 3TARGET = test.exe 4SRCS = test.cpp 5OBJS = test.o 6INCDIR = -Ic:/msys64/mingw64/include 7LIBDIR = -Lc:/msys64/mingw64/lib 8LIBS = -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib 9$(TARGET): $(OBJS) 10 $(CC) -o $@ $^ $(LIBDIR) $(LIBS) 11$(OBJS): $(SRCS) 12 $(CC) $(CFLAGS) -fexec-charset=cp932 $(INCDIR) -c $(SRCS) 13
だったのですがアドバイスの通りやってみたのですが、(pacmanの実行とmakefileの修正)
makefile
1 CC = c:/msys64/mingw64/bin/g++ 2 CFLAGS = 3 TARGET = test.exe 4 SRCS = test.cpp 5 OBJS = test.o 6 LIBDIR = -Lc:/msys64/mingw64/lib 7 LIBS = -licudt -licuin -licuio -licutest -licutu -licuuc 8 $(TARGET): $(OBJS) 9 $(CC) -o $@ $^ $(LIBDIR) $(LIBS) 10 $(OBJS): $(SRCS) 11 $(CC) $(CFLAGS) -fexec-charset=cp932 $(INCDIR) -c $(SRCS)
今度はこのようなエラーが発生してしまいました
c:/msys64/mingw64/bin/g++ -fexec-charset=cp932 -c test.cpp c:/msys64/mingw64/bin/g++ -o test.exe test.o -Lc:/msys64/mingw64/lib -licudt -licuin -licuio -licutest -licutu -licuuc C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x5e): undefined reference to `icu_73::StringPiece::StringPiece(char const* )' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x8a): undefined reference to `icu_73::UnicodeString::fromUTF8(icu_73::Stri ngPiece)' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0xa5): undefined reference to `icu_73::UnicodeString::char32At(int) const' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x126): undefined reference to `icu_73::UnicodeString::~UnicodeString()' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x163): undefined reference to `icu_73::UnicodeString::~UnicodeString()' collect2.exe: error: ld returned 1 exit status make: *** [C:/CPP/_.mk:9: test.exe] Error 1
このあと、アドバイス(CFLAGS = -DU_DISABLE_RENAMING=1)通りに変更するとこのようなエラーになりました
c:/msys64/mingw64/bin/g++ -DU_DISABLE_RENAMING=1 -fexec-charset=cp932 -c test.cpp c:/msys64/mingw64/bin/g++ -o test.exe test.o -Lc:/msys64/mingw64/lib -licudt -licuin -licuio -licutest -licutu -licuuc C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x5e): undefined reference to `icu::StringPiece::StringPiece(char const*)' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x8a): undefined reference to `icu::UnicodeString::fromUTF8(icu::StringPiec e)' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0xa5): undefined reference to `icu::UnicodeString::char32At(int) const' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x126): undefined reference to `icu::UnicodeString::~UnicodeString()' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe : test.o:test.cpp:(.text+0x163): undefined reference to `icu::UnicodeString::~UnicodeString()' collect2.exe: error: ld returned 1 exit status make: *** [c:/CPP/_.mk:9: test.exe] Error 1
-licudt.lib
と書くことでで、リンクしたいと思っているファイルのファイル名をフルパスで書いてください。
c:/msys64/mingw64/lib/icudt.lib
c:/msys64/mingw64/lib/icuin.lib
c:/msys64/mingw64/lib/icuio.lib
c:/msys64/mingw64/lib/icutest.lib
c:/msys64/mingw64/lib/icutu.lib
c:/msys64/mingw64/lib/icuuc.lib
なんと。普通は ~~\lib\libicudt.a などです。
gcc の -l オプションはこのネーミングが前提で、普通の libicudt.a をリンクしたい場合は、
先頭のlibと拡張子を外して、-licutdt と書きます。
-licudt.lib と書くと、libicudt.lib.a という名前のファイルを探します。で、No such file or directory
これは、普通に pacman コマンドでインストールした物ですか?
名前が変なので、別の環境用のファイルを自分でここにコピーしたとか言うことではないのでしょうか?
確かにコピーしたものですpacmanでやってみます
質問者さん
ujimushi_sradjpさんの回答の
-LIBS = -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib
+LIBS = -licudt -licuin -licuio -licutest -licutu -licuuc
は、
LIBS = -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib
↓ 修正
LIBS = -licudt -licuin -licuio -licutest -licutu -licuuc
という意味ですが、それは大丈夫でしょうか?
知りませんでした...
しかし、それを修正しても変わりませんでした
「変わりませんでした」だけでは、現状どうなってるのかが分かりません
ujimushi_sradjpさんの回答内容と同じこと(「pacman」の実行と「Makefile」の修正)を行ってから、「make」を実行して表示された内容を、質問を編集して追記してください
> undefined reference to ~~
というのは、関数名を間違えているか、-l で指定するライブラリが足りないかどちらかです。
icuライブラリの使い方を調べたことが無いので、どちらなのかは分かりませんが。
chatGPTにプログラムを聞くのはそれが合っているか間違っているか判断できるスキルがある人向けでは?
質問の最初の時点のmakefileの
> LIBS = -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib
でmakeを実行したら、
> c:/msys64/mingw64/bin/g++ -o test.exe test.o -Lc:/msys64/mingw64/lib -licudt.lib -licuin.lib -licuio.lib -licutest.lib -licutu.lib -licuuc.lib
と、「LIBS」の内容の「-licudt.lib...-licuuc.lib」が付いてg++が実行されてました
一方、makefileを
> LIBS = -licudt -licuin -licuio -licutest -licutu -licuuc
に修正してmakeを実行したら、
> c:/msys64/mingw64/bin/g++ -o test.exe test.o -Lc:/msys64/mingw64/lib
と、「LIBS」の内容の「-licudt...-licuuc」が付かずにg++が実行されてます
これは、実行結果を質問にコピペする際のミスではなく、実際にそうなのでしょうか?
もし実際にそうなら、makefileで「LIBS =...」の行以外を触ってませんでしょうか?
質問の修正後のmakefileでも、最初のmakefileと同じ
> $(CC) -o $@ $^ $(LIBDIR) $(LIBS)
なので、g++実行に「LIBS」の内容が付かないのは不思議です
現状のmakefileの「LIBS =...」の行を質問の最初のに戻してmakeを実行したら、g++実行に「LIBS」の内容が付いて「No such file or directory」エラーが再現するのでしょうか?
-l ~~ が付いてないエラーメッセージって、LIB = ~~ でなく -LIBS = ~~ と +LIBS = ~~ と書いてたときの物かと思ってたのですが、違うのか???
現在でもコマンドラインに -l ~~ がついてないのであれば、 LIBS = ~~ の所の修正がミスっているためと思います。
otnさん
> -l ~~ が付いてないエラーメッセージって、LIB = ~~ でなく -LIBS = ~~ と +LIBS = ~~ と書いてたときの物
そのようですね
質問が編集されて、現在は「-licudt...-licuuc」が付いてます
現状の質問の一つ前の編集が正しいという前提で前のコメントを書いたのですが
> undefined reference to `icu_73::UnicodeString::~UnicodeString()'
makefileで、
CFLAGS =
↓ 変更
CFLAGS = -DU_DISABLE_RENAMING=1
としてみてください
参考
https://blog.lukhnos.org/2009-2012/6441462604.html
https://stackoverflow.com/questions/35246695/undefined-reference-to-icu-56unicodestringunicodestringsigned-char-unsign
同じエラーが発生します...
makeを実行する前に「test.o」を削除しましたでしょうか?
test.oは削除しました
> test.oは削除しました
の後にmakeを実行したら、
c:/msys64/mingw64/bin/g++ -DU_DISABLE_RENAMING=1 -fexec-charset=cp932 -c test.cpp
と、「-DU_DISABLE_RENAMING=1」が付いて表示されましたでしょうか?
> 同じエラーが発生します
「全く同じ」エラーでしょうか?
エラーメッセージの
> undefined reference to `icu_73::UnicodeString::~UnicodeString()'
の「_73」が変わったりしてませんでしょうか?
すみません よく見てみたらtest.oを削除する前 CFLAGS = -DU_DISABLE_RENAMING=1 に変更したときにエラーメッセージが変わっていました
質問に補足します
最初にこの質問をした時点で
> ICUの.libファイル(icuin.lib icuio.lib icutest.lib icutu.lib icuuc.lib)はc:/msys64/mingw64/libに置いています
.hファイルはc:/msys64/mingw64/include/unicodeに置いています
に置いてあった
> 確かにコピーしたものです
のヘッダーファイルとライブラリファイルは、pacmanでインストールする前に削除しましたでしょうか?
エラーメッセージからの推測ですが、ヘッダーファイルとライブラリファイルのバージョンが違うように思います
ライブラリファイルは、元々のはファイル名が「*.lib」でしたが、現状のmakefileで指定してるのはファイル名に「.lib」が付いてないものなので、pacmanでインストールしたものが使われてると思います
(質問者さんが「*.lib」のファイル名を変えて「.lib」を取ったりしてませんよね?)
そこで、ヘッダーファイルがpacmanでインストールしたのとは違うものが読み込まれてるのではないか、と想像しました
【追記】
もし、pacmanでインストールする前から置いてあったヘッダーファイルとライブラリファイルがまだ残ってるなら、それらを削除して、makefileの「CFLAGS =」の行を元に戻して、「test.o」を削除してから、makeを実行してみてください
「*.lib」のファイル名を変えて「.lib」を取ったりはしていませんが、やってみます
コンパイルできました! 本当にありがとうございます
解決したようで良かったです。
おわかりかと思いますが、失敗は、icuのライブラリーが必要なのに、MSYS2用のものをインストールせずに、違う環境用のファイルをMSYS2のディレクトリーにコピーして使おうとしたことです。
ライブラリーは環境毎に違います。(近縁の環境で共有できるケースもありますが)
ただ、まあ、考えてみるとプログラミングの入門書は、実機での例を書きながら解説している場合、1つの環境を用いて書いていると思うので、「他の環境のライブラリーをコピーしても使えない」旨は書いてない気がします。初心者はそういうことをどうやっで学べば良いのかを考えると、今回、やむを得ない間違いなのかも知れません。本当はプログラミングの勉強の前に「コンピューターの仕組み」を学べば万全ですが。
